﻿using System;
using System.Collections;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using HighDiveEngine.Aggregates;
using HighDiveEngine.Model;
using HighDiveEngine.Resources;
using HighDiveJudge.Interfaces;
using HighDiveJudge.Resources;

namespace HighDiveJudge
{
    public partial class JudgeAppForm : Form, IJudgeAppForm
    {
        #region Properties

        private Dive CurrentDive { get; set; }

        private DiveList History { get; set; }

        private ArrayList HistoryArrayList { get; set; }

        #endregion
        
        #region Constructor
        public JudgeAppForm()
        {
            InitializeComponent();
        }
        #endregion

        #region Views

        public void ShowView(FormViews panel)
        {
            switch (panel)
            {
                case FormViews.LoggedIn:
                    LoginSuccesful();
                    break;
                case FormViews.LoggedOut:
                    Logout();
                    break;
                case FormViews.ToggleEditScore:
                    ToggleEditScore();
                    break;
            }
        }

        private void LoginSuccesful()
        {            
            panelLogin.Visible = false;
            panelContest.Visible = true;
            toolStripMenuItemLogout.Visible = true;
        }

        

        private void Logout()
        {
            buttonConnect.Enabled = true;
            textBoxIpOctette1.Enabled = true;
            textBoxIpOctette2.Enabled = true;
            textBoxIpOctette3.Enabled = true;
            textBoxIpOctette4.Enabled = true;
            textBoxAdminPort.Enabled = true;
            textBoxListenPort.Enabled = true;
            textBoxIdString.Enabled = true;
            panelLogin.Visible = true;
            panelContest.Visible = false;
            toolStripMenuItemLogout.Visible = false;
        }

        private void ToggleEditScore()
        {
            groupBoxRecentJumps.Visible = !groupBoxRecentJumps.Visible;
            groupBoxEditScore.Visible = !groupBoxEditScore.Visible;
        }

        private void _populateEditDiveFields(Dive dive)
        {
            labelEditScoreDiver.Text = dive.Diver.FirstName + " " + dive.Diver.LastName;
            labelEditScoreStartNumber.Text = dive.Diver.StartNumber.ToString();
            labelEditScoreDiveCode.Text = dive.DiveCode;
            labelEditScoreDiveNumber.Text = dive.DiveNumber.ToString();
            labelEditScoreDiveHeight.Text = dive.DiveHeight.ToString();
            labelEditScoreDifficulty.Text = Convert.ToDouble(dive.Difficulty).ToString(CultureInfo.InvariantCulture);
            comboBoxEditScore.Text = dive.DiveScoreList[0].Score.ToString(CultureInfo.InvariantCulture);
        }

        #endregion

        #region Public Methods

        public void LoginRefused()
        {
            MessageBox.Show("Login refused! Bad ID Key?");
            Invoke(new MethodInvoker(Logout));
        }

        public void ConnectionFailed()
        {            
            Invoke(new MethodInvoker(Logout));
            MessageBox.Show("Connection Failed!");
        }

        public void ContestEnded()
        {
            Invoke(new MethodInvoker(Logout));
            MessageBox.Show("Contest ended by admin!\n Goodbye!");
        }

        public void UpdateShownDives(Dive currentDive, DiveList history)
        {
            CurrentDive = currentDive;
            History = history;

            if (currentDive == null)
                groupBoxCurrentJump.Visible = false;
            else
            {
                groupBoxCurrentJump.Visible = true;
                labelDiver.Text = currentDive.Diver.FirstName + " " + currentDive.Diver.LastName;
                labelStartNumber.Text = currentDive.Diver.StartNumber.ToString();
                labelDiveCode.Text = currentDive.DiveCode;
                labelDiveNumber.Text = currentDive.DiveNumber.ToString();
                labelDiveHeight.Text = currentDive.DiveHeight.ToString();
                labelDifficulty.Text = Convert.ToDouble(currentDive.Difficulty).ToString(CultureInfo.InvariantCulture);
                comboBoxScore.Text = "5";
            }

            HistoryArrayList = new ArrayList(history);
            listBoxRecentJumps.DataSource = HistoryArrayList;
        }

        #endregion

        #region Button Methods

        private void buttonSend_Click(object sender, EventArgs e)
        {
            if (EventSendScore != null)
                if (!(new Regex(@"^((10)|([0-9]([\.\,][05])?))$").IsMatch(comboBoxScore.Text)))
                    MessageBox.Show("Invalid score!");
                else
                {
                    comboBoxScore.Text = comboBoxScore.Text.Replace(",", ".");
                    EventSendScore(CurrentDive, Convert.ToDouble(comboBoxScore.Text, CultureInfo.InvariantCulture));
                }
        }

        private void buttonEditScoreSend_Click(object sender, EventArgs e)
        {
            if (EventSendScore != null)
                if (!(new Regex(@"^((10)|([0-9]([\.\,][05])?))$").IsMatch(comboBoxScore.Text)))
                    MessageBox.Show("Invalid score!");
                else
                {
                    comboBoxEditScore.Text = comboBoxEditScore.Text.Replace(",", ".");
                    groupBoxEditScore.Visible = false;
                    groupBoxRecentJumps.Visible = true;
                    EventSendScore((Dive)listBoxRecentJumps.SelectedItem, Convert.ToDouble(comboBoxEditScore.Text, CultureInfo.InvariantCulture));
                }
        }

        private void buttonEditScoreDiscard_Click(object sender, EventArgs e)
        {
            ToggleEditScore();
        }

        private void listBoxRecentJumps_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Y > listBoxRecentJumps.SelectedIndex*15 && e.Y < listBoxRecentJumps.SelectedIndex*15 + 15)
            {
                _populateEditDiveFields((Dive)listBoxRecentJumps.SelectedItem);
                ToggleEditScore();
            }
        }

        private void listBoxRecentJumps_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData.HasFlag(Keys.Enter))
            {
                _populateEditDiveFields((Dive)listBoxRecentJumps.SelectedItem);
                ToggleEditScore();
            }
        }

        private void buttonConnect_Click(object sender, EventArgs e)
        {
            if (EventLogin != null)
            {
                textBoxIpOctette1.Text = textBoxIpOctette1.Text.Trim();
                textBoxIpOctette2.Text = textBoxIpOctette2.Text.Trim();
                textBoxIpOctette3.Text = textBoxIpOctette3.Text.Trim();
                textBoxIpOctette4.Text = textBoxIpOctette4.Text.Trim();
                textBoxAdminPort.Text = textBoxAdminPort.Text.Trim();
                textBoxListenPort.Text = textBoxListenPort.Text.Trim();
                textBoxIdString.Text = textBoxIdString.Text.Trim();

                //regex check on textboxes to see that the values are OK
                if (!(new Regex(@"^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$").IsMatch(textBoxIpOctette1.Text)))
                    MessageBox.Show("Invalid Ip adress!");
                else if (!(new Regex(@"^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$").IsMatch(textBoxIpOctette2.Text)))
                    MessageBox.Show("Invalid Ip adress!");
                else if (!(new Regex(@"^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$").IsMatch(textBoxIpOctette3.Text)))
                    MessageBox.Show("Invalid Ip adress!");
                else if (!(new Regex(@"^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$").IsMatch(textBoxIpOctette4.Text)))
                    MessageBox.Show("Invalid Ip adress!");
                else if (!(new Regex(@"^([0-9]{4,5})$").IsMatch(textBoxAdminPort.Text)))
                    MessageBox.Show("Invalid admin port!");
                else if (!(new Regex(@"^([0-9]{4,5})$").IsMatch(textBoxListenPort.Text)))
                    MessageBox.Show("Invalid listen port!");
                else if (!(new Regex(@"^([a-zA-Z0-9]{5})$").IsMatch(textBoxIdString.Text)))
                    MessageBox.Show("Invalid ID key!");
                else
                {   //all values OK, attempt connect
                    buttonConnect.Enabled = false;
                    textBoxIpOctette1.Enabled = false;
                    textBoxIpOctette2.Enabled = false;
                    textBoxIpOctette3.Enabled = false;
                    textBoxIpOctette4.Enabled = false;
                    textBoxAdminPort.Enabled = false;
                    textBoxListenPort.Enabled = false;
                    textBoxIdString.Enabled = false;
                    EventLogin(textBoxIdString.Text,
                        textBoxIpOctette1.Text + "." + textBoxIpOctette2.Text + "." + textBoxIpOctette3.Text + "." +
                        textBoxIpOctette4.Text + ":" + Convert.ToInt32(textBoxAdminPort.Text),
                        Convert.ToInt32(textBoxListenPort.Text));
                }
            }
        }

        private void buttonExit_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void logoutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (EventLogout != null)
                EventLogout();
        }

        private void quitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        #endregion

        #region IJudgeAppForm

        public event DelegateVoidDiveDouble EventSendScore;
        public event DelegateVoidStringStringInt EventLogin;
        public event MethodInvoker EventLogout;

        #endregion

        
    }
}
